﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows.Controls.Ribbon;
using SHomeWorkshop.LunarConcept.Controls;
using System.Xml;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.ModifingManager;
using System.Windows;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;

namespace SHomeWorkshop.LunarConcept.Commands
{
    /// <summary>
    /// 创建时间：2012年1月18日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：将当前组合起来的部件取消组合。
    /// </summary>
    public static class UnGroupWidgetCommand
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态][构造方法]
        /// 
        /// ——此方法会初始化并向WPF系统注册一个RoutedUICommand。
        /// </summary>
        static UnGroupWidgetCommand()//类型构造器
        {
            routedUICmd = new RoutedUICommand(
                "UnGroupWidgetCommand",
                "UnGroupWidgetCommand",
                typeof(UnGroupWidgetCommand),//创建RoutedUICommand对象
                null);//本程序考虑支持“命令模式”因此，这些命令完全没有必要直接支持快捷键。

            routedUICmd.InputGestures.Add(new KeyGesture(Key.G, ModifierKeys.Control | ModifierKeys.Shift, "Ctrl + Shift + G"));

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        #endregion

        #region 字段与属性===================================================================================================

        private static CommandBinding cmdBinding = new CommandBinding();
        /// <summary>
        /// 用在主窗口CommandBindings集合中的命令绑定。
        /// 
        /// 它的Command是RoutedUICommand。
        /// ——因此，RoutedUICommand是否可以运行将由CmdBinding的CanExecute事件决定。
        /// ——而且，RoutedUICommand的执行也是通过CmdBinding的Execute事件来进行的。
        /// </summary>
        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        private static RoutedUICommand routedUICmd;
        /// <summary>
        /// [只读静态属性]表示在WPF系统中注册的一个RoutedUICommand。
        /// ——必须和CommandBinding配合才能使用。
        ///     CommandBinding要添加到主窗口的CommandBindings集合中；
        ///     RoutedUICommand则要向WPF系统注册。
        ///     
        /// ★说明：使用静态属性是因为这样在Xaml代码中比较便于绑定。
        /// </summary>
        public static RoutedUICommand RoutedUICmd
        {
            get { return routedUICmd; }
        }

        #endregion

        #region 方法=========================================================================================================

        /// <summary>
        /// 判断命令是否可以执行。
        /// ——由于可以直接调用Execute()方法，因此，即使被禁用，也不是不能执行相关功能！！！
        /// </summary>
        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //考虑到性能问题，全部取消此判断。反正执行时会判断。
            //if (Globals.MainWindow == null)
            //{
            //    e.CanExecute = false; return;
            //}

            //EditorManager manager = Globals.MainWindow.EditorManager;
            //if (manager == null)
            //{
            //    e.CanExecute = false; return;
            //}

            //Widgets.Widget selWidget = manager.GetMainSelectedWidget();

            //if (selWidget == null)
            //{
            //    e.CanExecute = false; return;
            //}

            //Widgets.GroupWidget gw = selWidget as Widgets.GroupWidget;
            //if (gw == null)
            //{
            //    e.CanExecute = false; return;
            //}

            e.CanExecute = true; return;
        }

        /// <summary>
        /// 命令被触发时，会调用本事件处理器方法。
        /// ——本方法实际上是调用ExeCute()这个静态方法来实现特定功能。
        /// </summary>
        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            LunarMessage.Warning(Execute());
        }

        /// <summary>
        /// [公开静态方法]即使此命令处于禁用状态，也可以通过代码调用此方法来执行特定任务！！！
        /// 
        /// 当被绑定的命令被调用（触发）时，会引发cmdBinding_Executed事件。
        /// 在cmdBinding_Executed事件处理器方法中已添加了调用Execute()方法的代码。
        /// 
        /// ——因此，触发命令，就相当于调用此方法！！！
        /// </summary>
        public static string Execute()
        {
            if (Globals.MainWindow == null) return "　　未找到Globals.MainWindow。";

            EditorManager manager = Globals.MainWindow.EditorManager;
            if (manager == null) return "　　未找到页面管理器。";

            Widgets.GroupWidget gw = manager.GetMainSelectedWidget() as Widgets.GroupWidget;
            if (gw == null || gw.XmlData == null) return "　　当前活动部件不是【组】。";

            XmlNode insideWidgetSetNode = gw.XmlData.SelectSingleNode(XmlTags.WidgetSetTag);

            if (insideWidgetSetNode == null) return "　　未找到组部件内部Xml数据中的【WidgetSet】节点。";

            XmlNodeList insideWidgetsNodes = insideWidgetSetNode.SelectNodes(XmlTags.WidgetTag);

            if (insideWidgetsNodes.Count <= 0) return "　　组部件内部没有下级部件。";

            PageEditor mainPage = gw.MasterEditor;
            if (mainPage == null)
            {
                return "　　发生意外情况：要取消的组合找不到所属的页面。";
            }

            XmlNode outsideWidgetSetNode = mainPage.XmlData.SelectSingleNode("WidgetSet");
            if (outsideWidgetSetNode == null) return "　　未找到活动页面Xml数据中的【WidgetSet】节点。";

            ModifingInfo info = new ModifingInfo() { ModifingDescription = "取消组合" };
            mainPage.MasterManager.GetSelectedPageEditorStatus(info);
            mainPage.MasterManager.GetSelectedWidgetStatus_Old(info);

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            //分解某个“组”之前，应先删除挂接到它身上的所有链接线。
            List<Widgets.Widget> gwList = new List<Widgets.Widget>();
            gwList.Add(gw);
            List<ILinkableLine> linkLines = gw.MasterEditor.GetLinkedLines(gwList);

            foreach (Widgets.Interfaces.ILinkableLine linkedLine in linkLines)
            {
                Widgets.ArrowLineWidget sline = linkedLine as Widgets.ArrowLineWidget;
                if (sline == null) continue;

                Action actDelLine = new Action(ActionType.WidgetDeleted, gw.MasterEditor.Id, sline.Id,
                    sline.XmlData.OuterXml, null);
                if (sline.XmlData.ParentNode == gw.MasterEditor.XmlData)
                {
                    gw.MasterEditor.XmlData.RemoveChild(sline.XmlData);
                }
                gw.MasterEditor.RemoveWidget(sline);

                mi.AddAction(actDelLine);
            }

            Point baseTopLeft = new Point(gw.Location.X + gw.WidgetPadding.Left, gw.Location.Y + gw.WidgetPadding.Top);

            string oldGroupOuterXml = gw.XmlData.OuterXml;
            //不能在删除子节点后再存入撤销列表。
            Action actDeleteGroupWidget = new Action(ActionType.WidgetDeleted, mainPage.Id, gw.Id,
                oldGroupOuterXml, null);

            //for (int i = insideWidgetsNodes.Count - 1; i >= 0; i--)//这会导致分解后部件层级颠倒。
            for (int i = 0; i < insideWidgetsNodes.Count; i++)
            {
                XmlNode node = insideWidgetsNodes[i];
                outsideWidgetSetNode.AppendChild(node);

                Widgets.Widget w = Widgets.Widget.BuildWidget(mainPage, node);

                Widgets.LineWidget lw = w as Widgets.LineWidget;
                if (lw != null)
                {
                    lw.RefreshPointWhenGroupOut(baseTopLeft);
                }
                else
                {
                    Widgets.ContentWidget cw = w as Widgets.ContentWidget;
                    cw.Location = new Point(cw.Location.X + baseTopLeft.X, cw.Location.Y + baseTopLeft.Y);
                }

                Action actInsertWidget = new Action(ActionType.WidgetAdded, mainPage.Id, w.Id,
                    null, w.XmlData.OuterXml);
                mainPage.AddWidget(w);
                mi.AddAction(actInsertWidget);

                ILinkableLine linkedLine = lw as ILinkableLine;
                if (linkedLine != null && linkedLine.IsLinked)
                {
                    mainPage.RefreshLinkedLines(mi, linkedLine);
                }

                info.AddWidgetID_NewSelected(w.Id);
                w.IsSelected = true;

                if (i == 0)
                {
                    w.IsMainSelected = true;
                    info.NewMainSelectedWidgetID = w.Id;
                }
            }

            //最后，删除“组”            
            if (outsideWidgetSetNode == gw.XmlData.ParentNode)
            {
                outsideWidgetSetNode.RemoveChild(gw.XmlData);
            }

            mainPage.RemoveWidget(gw);
            mi.AddAction(actDeleteGroupWidget);

            gw.IsSelected = false;//目的是从SelectedWidtesList中去除已不需要的“组”部件。

            if (mainPage.MasterManager != null)
            {
                mainPage.MasterManager.RegisterModifingItem(mi);
                mainPage.MasterManager.RefreshAutoNumberStrings();
            }

            return string.Empty;
        }

        #endregion
    }
}
